package go_xxljob_excutor

import (
	"gitee.com/youbeiwuhuan/go-xxljob-executor/biz/client"
	. "gitee.com/youbeiwuhuan/go-xxljob-executor/global"
	"gitee.com/youbeiwuhuan/go-xxljob-executor/handler"
	"gitee.com/youbeiwuhuan/go-xxljob-executor/proccess"
	"gitee.com/youbeiwuhuan/go-xxljob-executor/run"
	"gitee.com/youbeiwuhuan/go-xxljob-executor/server"
	toolsZap "gitee.com/youbeiwuhuan/go-xxljob-executor/tools/zap"
	"go.uber.org/zap"
	"strings"
)

var (
	triggerCallback            *proccess.TriggerCallbackProccessor
	bizServer                  *server.ExecutorBizServer
	executorRegistryProccessor *proccess.ExecutorRegistryProccessor
	jobLogFileCleanProccessor *proccess.JobLogFileCleanProccessor
)

type XxljobExcutor struct {
	adminAddresses string
	accessToken    string
	appname        string

	//注册地址
	address string
	//本地绑定ip
	ip string
	//本地监听端口
	port             int32
	logPath          string
	logRetentionDays int32
}

func NewXxljobExcutor(
	adminAddresses string,
	accessToken string,
	appname string,

	address string,
	ip string,
	port int32,
	logPath string,
	logRetentionDays int32) *XxljobExcutor {
	return &XxljobExcutor{
		adminAddresses: adminAddresses,
		accessToken:    accessToken,
		appname:        appname,

		address:          address,
		ip:               ip,
		port:             port,
		logPath:          logPath,
		logRetentionDays: logRetentionDays,
	}
}

func (xe *XxljobExcutor) Start() {
	XxlLogPath = xe.logPath
	Logger = InitZapLogger(XxlLogPath)

	AdminBizList = InitAdminBizList(xe.adminAddresses, xe.accessToken)

	triggerCallback = InitTriggerCallbackProccessor()

	bizServer = InitBizServer(xe.ip, xe.port, xe.accessToken, triggerCallback)

	executorRegistryProccessor = InitExecutorRegistryProccessor(xe.appname, xe.address)

	jobLogFileCleanProccessor = InitJobLogFileCleanProccessor(xe.logRetentionDays,xe.logPath)

}

func (xe *XxljobExcutor) Destroy() {

	if nil != triggerCallback {
		triggerCallback.Stop()
	}

	if nil != bizServer {
		bizServer.Stop()
	}
	if nil != executorRegistryProccessor {
		executorRegistryProccessor.Stop()
	}


	if nil != jobLogFileCleanProccessor {
		jobLogFileCleanProccessor.Stop()
	}

}

//  添加IJobHandler
// @auth      Frank Fan
// @param     handlerName string
// @param     handler IJobHandler
// @return
func (xe *XxljobExcutor) AddJobHandler(handlerName string, handler handler.IJobHandler) {
	run.AddJobHandler(handlerName, handler)
}

// ---------------- 一下是初始化方法-------------------------------------------------------------------------------------------------------------------------------------------------------------
func InitZapLogger(logPath string) *zap.Logger {
	zapConfig := toolsZap.ZapConfig{
		Level:         "info",
		Format:        "console",
		Prefix:        "[xxl-job-executor]",
		Director:      logPath + "/logs",
		LinkName:      "latest_log",
		ShowLine:      true,
		EncodeLevel:   "LowercaseColorLevelEncoder",
		StacktraceKey: "stacktrace",
		LogInConsole:  true,
	}

	return toolsZap.InitZap(zapConfig)
}

func InitAdminBizList(adminAddresses string, accessToken string) []*client.AdminBizClient {
	if "" == adminAddresses {
		return nil
	}

	addrs := strings.Split(adminAddresses, ",")

	adminBizList := make([]*client.AdminBizClient, len(addrs))

	for i, addr := range addrs {
		adminBizList[i] = client.NewAdminBizClient(addr, accessToken, 3)
	}

	return adminBizList

}

func InitBizServer(ip string, port int32, accessToken string, triggerCallback *proccess.TriggerCallbackProccessor) *server.ExecutorBizServer {
	biz := server.NewExecutorBizImpl(triggerCallback)

	bizServer := server.NewExecutorBizServer(ip, port, accessToken, biz)

	bizServer.Start()

	return bizServer
}

func InitTriggerCallbackProccessor() *proccess.TriggerCallbackProccessor {

	triggerCallback := proccess.NewTriggerCallbackProccessor()
	triggerCallback.Start()

	return triggerCallback

}

func InitExecutorRegistryProccessor(appname string, address string) *proccess.ExecutorRegistryProccessor {

	prc := proccess.NewExecutorRegistryProccessor(appname, address)

	prc.Start()

	return prc

}


func InitJobLogFileCleanProccessor(logRetentionDays int32, xxlLogPath string)*proccess.JobLogFileCleanProccessor{
	prc := proccess.NewJobLogFileCleanProccessor(logRetentionDays,xxlLogPath)
	prc.Start()
	return prc
}

